-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] construct text frames on UI thread. #45418
Conversation
A second component to this change is that the public API for getting bitmap/emoji font requires a Skia paragraph object, and so moving the text frame construction allows us to (later) fix that too |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a few comments.
@@ -1302,6 +1302,48 @@ void DisplayListBuilder::DrawTextBlob(const sk_sp<SkTextBlob>& blob, | |||
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags); | |||
drawTextBlob(blob, x, y); | |||
} | |||
|
|||
void DisplayListBuilder::drawTextFrame( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that drawTextBlob
will go unused in the Impeller backend?
If so, would you want to (ifdef'd?) make sure it's not used, i.e. UNIMPLEMENTED
, similar to the dispatcher?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we use DisplayListBuilder on Skia ever. FYI @flar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we do. That was its original purpose and is iteratively becoming its only purpose.
return; | ||
} | ||
impeller::Rect bounds = text_frame->GetBounds(); | ||
SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised we don't have a conversion for this? If we don't, feel free to resolve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, its just all over the place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we would want to just do a separate class at some point versus having all these switches?
(No changes requested in this PR, more of an open question/possible TODO)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that ultimately depends on how many (if any) additional checks we need to add versus how quickly we move through preview for the remaining platforms. I wouldn't think so at this time, but if we have to do much more than splitting into two might make sense. however is still 80% the same code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At one point DL was supposed to be an agnostic storage format that could be used for any backend, allowing common operations at the "picture" level. There was potential for more value added operations that we never pursued. Meanwhile performance considerations related to conversions have been driving it into custom backend-specific cases.
@@ -180,6 +202,14 @@ class DisplayListParagraphPainter : public skt::ParagraphPainter { | |||
return path; | |||
} | |||
|
|||
bool ShouldRenderAsPath(const DlPaint& paint) const { | |||
// Text with non-trivial color sources or stroke paint mode should be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding context.
Is this for performance or correctness or both? Could you note that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added correctness information.
@@ -79,6 +82,20 @@ class DisplayListParagraphPainter : public skt::ParagraphPainter { | |||
} | |||
size_t paint_id = std::get<PaintID>(paint); | |||
FML_DCHECK(paint_id < dl_paints_.size()); | |||
|
|||
if (ShouldRenderAsPath(dl_paints_[paint_id])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider putting this inside the impeller_enabled_
block below, and FML_DCHECK'ing instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you also want to guard this with IMPELLER_SUPPORTS_RENDERING
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
How expensive are the TextBlobs themselves? If we kept both around then we'd retain the ability to render a DL under both Skia and Impeller, but at the cost of storing both. That isn't our long-term goal, but it keeps some ability to remain backend-agnostic while we get there. |
The text blobs themselves won't be expensive to store, once we have them we have them. But DLs isn't backend agnostic, as both images/textures and shaders are backend specific now. |
…134089) flutter/engine@5903490...8bacc3b 2023-09-06 [email protected] [Impeller] construct text frames on UI thread. (flutter/engine#45418) 2023-09-06 [email protected] Add import for `<unordered_map>` to fix the g3 build (flutter/engine#45471) 2023-09-06 [email protected] Roll Skia from af473004622f to 0a253625a76a (2 revisions) (flutter/engine#45470) 2023-09-05 [email protected] Roll Skia from 1019c10a2d38 to af473004622f (2 revisions) (flutter/engine#45469) 2023-09-05 [email protected] Adds a comment on clang_arm64_apilevel26 toolchain usage (flutter/engine#45467) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This reverts commit 8bacc3b.
Reverts #45418 Some google3 tests are hitting the CHECK I added in the DlSkCanvasDispatcher::drawTextFrame, which indicates that the SkParagraph code likely thinks impeller is enabled, whereas other code might be running with Skia. Perhaps this could happen if its software rendering? It should be a fatal error on startup so we can track this down.
Reverts flutter#45418 Some google3 tests are hitting the CHECK I added in the DlSkCanvasDispatcher::drawTextFrame, which indicates that the SkParagraph code likely thinks impeller is enabled, whereas other code might be running with Skia. Perhaps this could happen if its software rendering? It should be a fatal error on startup so we can track this down.
Reverts flutter#45418 Some google3 tests are hitting the CHECK I added in the DlSkCanvasDispatcher::drawTextFrame, which indicates that the SkParagraph code likely thinks impeller is enabled, whereas other code might be running with Skia. Perhaps this could happen if its software rendering? It should be a fatal error on startup so we can track this down.
…ad." (#45910) (#45958) Reverts #45418 Some google3 tests are hitting the CHECK I added in the DlSkCanvasDispatcher::drawTextFrame, which indicates that the SkParagraph code likely thinks impeller is enabled, whereas other code might be running with Skia. Perhaps this could happen if its software rendering? It should be a fatal error on startup so we can track this down. cherry pick for flutter roll Co-authored-by: Jonah Williams <[email protected]>
Reverts #45418 Some google3 tests are hitting the CHECK I added in the DlSkCanvasDispatcher::drawTextFrame, which indicates that the SkParagraph code likely thinks impeller is enabled, whereas other code might be running with Skia. Perhaps this could happen if its software rendering? It should be a fatal error on startup so we can track this down.
Conversion of SkTextBlobs to impeller::TextFrame objects is one of the most expensive operations in display list dispatching. While the rest of the engine and framework makes a reasonable attempt to cache the SkTextBlobs generated during paragraph construction, the design of the dl dispatcher means that these the Impeller backend will always reconstruct all text frames on each frame - even if the display list/picture that contained those text frames was unchanged.
Removing this overhead is one of the goals of #45386 , however this patch is also fairly risky and will be difficult to land. As a more incremental solution, we can instead construct the impeller::TextFrame objects when performing paragraph painting and record them in the display list. This both moves the text frame construction to the UI thread and allows the framework/engine to cache unchanged text frames.
This also does not conflict with the dl_aiks_canvas patch directly, and is fine to land before or after it does. (though I'd argue we should land this first).
To compare the current performance levels, I ran the complex_layout_scroll perf test, since this is fairly text filled. On a Pixel 6 pro. Across several runs this is a fairly consistent ~1ms raster time improvement.
Skia
Impeller (ToT)
Impeller (Patched)